package com.xinyue.auto.reader.process;

import java.util.List;

import org.dom4j.Element;
import org.dom4j.Node;

import com.xinyue.auto.bean.Query;
import com.xinyue.auto.exception.QueryException;
import com.xinyue.auto.reader.Process;
import com.xinyue.auto.reader.major.FindMajor;
import com.xinyue.auto.reader.util.OrderUtil;
import com.xinyue.auto.reader.util.SetterUtil;
import com.xinyue.auto.type.Comparator;
import com.xinyue.auto.type.Type;
import com.xinyue.auto.util.StringUtil;

public class QueryProcess extends FindMajor implements Type, Comparator{
	public QueryProcess(Process read) {
		super(read);
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void validate() throws Exception {
		Element find = xml.element(finder_);
		if(find != null) {
			//读取query标签
			List<Element> qs = find.elements(query_);
			
			if(qs != null && qs.size() > 0) {
				try {
					for (Element query: qs) {
						//读取公共属性
						Query q = commonRead(query);
						q.setType(queryType);
						
						//返回值、强制类型转换、是否单个结果集处理
						queryReturn(query, q);
						//入参、paramSetter以及hql语句where子句预处理
						String where = queryParam(query, q);
						//order-by语句预处理
						String order = orderor(query);
						//合并查询语句
						q.setState(q.getState() + where + order);
						
						querys.add(q);
					}
				} catch (Exception e) {
					throw new QueryException(e.getMessage(), holder.getException());
				}
			}
		}
	}
	
	/**
	 * query返回值
	 * @param query
	 * @param q
	 * @throws FinderException
	 */
	private void queryReturn(Element query, Query q) throws Exception {
		String entity = xml.attributeValue(name_);
		
		String type = query.attributeValue(returnType_);
		if(StringUtil.isNull(type)) {
			throw new Exception("returnType属性未定义或其值为空:" + type);
		}
		
		String state = "from " + entity;
		//验证是否是entity
		if(entity.equals(type)) {
			q.setConvert(true);
			q.setOnly(true);
			q.setReturnType(entity);
		}else if(LIST.equals(type)) {
			q.setWarning(true);
			q.setReturnType("List<" + entity + ">");
		}else if(COUNT.equals(type)) {
			state = "select count(*) " + state;
			q.setConvert(true);
			q.setOnly(true);
			q.setReturnType(LONG_);
		}else {
			throw new Exception("returnType属性值非法:" + type);
		}
		
		q.setState(state);
	}
	
	/**
	 * 入参、paramSetter以及hql语句where子句预处理
	 * param query标签
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private String queryParam(Element query, Query q) throws Exception {
		List<Element> columns = query.elements(query_column_);
		if(columns == null || columns.size() == 0) {
			throw new Exception("必须定义query-column子标签");
		}
		
		String param = "";
		String paramIn = "";
		String where = null;
		String[] setter = new String[columns.size()];
		
		for (int i = 0; i < columns.size(); i++) {
			String name = columns.get(i).attributeValue(name_);
			if(StringUtil.isNull(name)) {
				throw new Exception("query-column标签未定义name属性或其值为空");
			}
			
			String type = getType(name);
			
			//合并参数
			param += type + " " + name + ", ";
			paramIn += name + ", ";
			//获取setter语句
			setter[i] = SetterUtil.setterHQL(name, type);
			//比较器验证并获得where子语句
			comparator(query, name, where);
		}
		
		q.setParamSetter(setter);
		q.setParams(param.substring(0, param.length() - 2));
		q.setParamsIn(paramIn.substring(0, paramIn.length() - 2));
		
		return " where " + where;
	}
	
	/**
	 * 验证query-column数据合法性并获得其属性类型
	 * @param name
	 * @return
	 * @throws Exception
	 */
	private String getType(String name) throws Exception {
		Node n = xml.selectSingleNode("id[@name='" + name + "']");
		if(n == null) {
			n = xml.selectSingleNode("property[@name='" + name + "']");
		}
		if(n == null) {
			throw new Exception("query-column标签name属性值未能和entity属性对应:" + name);
		}
		
		return n.valueOf("@type");
	}
	
	/**
	 * 验证order-column并返回order语句
	 * @param order
	 * @return
	 * @throws FinderException
	 */
	@SuppressWarnings("unchecked")
	private String orderor(Element query) throws Exception {
		Element order = query.element(order_by_);
		if(order == null) {
			return "";
		}
		
		List<Element> os = order.elements(order_column_);
		
		if(os == null || os.size() == 0) {
			throw new Exception("order标签未定义order-column子标签");
		}
		
		return OrderUtil.validate(os, xml);
	}
	
	/**
	 * 验证comparator并返回符合hibernate规范的where子句
	 * @throws FinderException
	 */
	private void comparator(Element query, String name, String where) throws Exception {
		String cpt = query.attributeValue(comparator_);
		String link = query.attributeValue(link_);
		
		String co = null;
		//处理比较符
		if(StringUtil.isNull(cpt)) {
			co = "=";
		}else {
			for (int i = 0; i < COMPARATS.length; i++) {
				if(COMPARATS[i].equals(cpt)) {
					co = cpt;
				}
			}
		}
		if(co == null) {
			throw new Exception("query-column标签comparator属性非法:" + cpt);
		}
		
		//处理连接字
		if(StringUtil.isNull(link)) {
			link = AND;
		}else if(!AND.equals(link) && !OR.equals(link)) {
			throw new Exception("query-column标签link属性非法:" + link);
		}
		
		if(!StringUtil.isNull(where)) {
			where += " " + link + " ";
		}
		
		if("like".equals(co)) {
			where += " " + link + " " + name + " like '%:" + name + "%'";
		}else {
			where += " " + link + " " + name + co + ":" + name;
		}
	}
}